/**
 * 窗口工厂模块
 * 使用函数式编程创建和管理Electron窗口
 * @author LYC
 * @date 2025-09-13
 */

import { BrowserWindow, shell } from 'electron'
import { join } from 'path'
import { is } from '@electron-toolkit/utils'
import { AppExitManager } from './app/appExit'

/**
 * 窗口配置接口
 */
export interface WindowConfig {
  width: number
  height: number
  minWidth?: number
  minHeight?: number
  show?: boolean
  resizable?: boolean
  maximizable?: boolean
  minimizable?: boolean
  autoHideMenuBar?: boolean
  titleBarStyle?: 'default' | 'hidden' | 'hiddenInset' | 'customButtonsOnHover'
  icon?: string
  webPreferences?: Electron.WebPreferences
}

/**
 * 路由配置接口
 */
export interface RouteConfig {
  hash: string
  url?: string
}

/**
 * 窗口事件处理器接口
 */
export interface WindowEventHandlers {
  onReadyToShow?: (window: BrowserWindow) => void
  onClose?: (event: Electron.Event, window: BrowserWindow) => void
  onClosed?: (window: BrowserWindow) => void
  onWindowOpenHandler?: (details: Electron.HandlerDetails) => { action: 'deny' | 'allow' }
}

/**
 * 创建基础窗口配置的纯函数
 */
export const createBaseWindowConfig = (
  width: number,
  height: number,
  icon: string
): WindowConfig => ({
  width,
  height,
  autoHideMenuBar: true,
  titleBarStyle: 'hiddenInset',
  icon,
  webPreferences: {
    preload: join(__dirname, '../preload/index.js'),
    sandbox: false,
    nodeIntegration: false,
    contextIsolation: true
  }
})

/**
 * 创建登录窗口配置的工厂函数
 */
export const createLoginWindowConfig = (
  width: number,
  height: number,
  icon: string
): WindowConfig => ({
  ...createBaseWindowConfig(width, height, icon),
  show: true,
  resizable: false,
  maximizable: false,
  minimizable: false
})

/**
 * 创建主窗口配置的工厂函数
 */
export const createMainWindowConfig = (
  width: number,
  height: number,
  minWidth: number,
  minHeight: number,
  icon: string
): WindowConfig => ({
  ...createBaseWindowConfig(width, height, icon),
  minWidth,
  minHeight,
  show: false, // 初始隐藏，登录成功后显示
  resizable: true,
  maximizable: true,
  minimizable: true
})

/**
 * 创建默认事件处理器的工厂函数
 */
export const createDefaultEventHandlers = (
  exitManager: AppExitManager,
  windowType: 'login' | 'main',
  onClosed?: (window: BrowserWindow) => void
): WindowEventHandlers => ({
  onReadyToShow: (window: BrowserWindow) => {
    window.show()

    // 开发环境自动打开DevTools
    if (is.dev && process.env.AUTO_OPEN_DEVTOOLS === 'true') {
      window.webContents.openDevTools()
    }
  },

  onClose: (event: Electron.Event) => {
    exitManager.handleWindowClose(event, windowType)
  },

  onClosed: onClosed,

  onWindowOpenHandler: (details: Electron.HandlerDetails) => {
    shell.openExternal(details.url)
    return { action: 'deny' }
  }
})

/**
 * 加载页面的纯函数
 */
export const loadPage = (window: BrowserWindow, route: RouteConfig): void => {
  if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
    window.loadURL(`${process.env['ELECTRON_RENDERER_URL']}#/${route.hash}`)
  } else {
    window.loadFile(join(__dirname, '../renderer/index.html'), {
      hash: route.hash
    })
  }
}

/**
 * 设置窗口事件监听器的纯函数
 */
export const setupWindowEvents = (window: BrowserWindow, handlers: WindowEventHandlers): void => {
  if (handlers.onReadyToShow) {
    window.on('ready-to-show', () => handlers.onReadyToShow!(window))
  }

  if (handlers.onClose) {
    window.on('close', (event) => handlers.onClose!(event, window))
  }

  if (handlers.onClosed) {
    window.on('closed', () => handlers.onClosed!(window))
  }

  if (handlers.onWindowOpenHandler) {
    window.webContents.setWindowOpenHandler(handlers.onWindowOpenHandler)
  }
}

/**
 * 创建窗口的高阶函数
 */
export const createWindow =
  (config: WindowConfig, route: RouteConfig, handlers: WindowEventHandlers) =>
  (): BrowserWindow => {
    // 创建窗口
    const window = new BrowserWindow(config)

    // 设置事件监听器
    setupWindowEvents(window, handlers)

    // 加载页面
    loadPage(window, route)

    return window
  }

/**
 * 窗口工厂类（函数式风格）
 */
export class WindowFactory {
  private static instance: WindowFactory
  private exitManager: AppExitManager

  private constructor(exitManager: AppExitManager) {
    this.exitManager = exitManager
  }

  public static getInstance(exitManager: AppExitManager): WindowFactory {
    if (!WindowFactory.instance) {
      WindowFactory.instance = new WindowFactory(exitManager)
    }
    return WindowFactory.instance
  }

  /**
   * 创建登录窗口的工厂方法
   */
  public createLoginWindow = (
    width: number,
    height: number,
    icon: string,
    onClosed?: (window: BrowserWindow) => void
  ): (() => BrowserWindow) => {
    const config = createLoginWindowConfig(width, height, icon)
    const route: RouteConfig = { hash: 'login' }
    const handlers = createDefaultEventHandlers(this.exitManager, 'login', onClosed)

    return createWindow(config, route, handlers)
  }

  /**
   * 创建主窗口的工厂方法
   */
  public createMainWindow = (
    width: number,
    height: number,
    minWidth: number,
    minHeight: number,
    icon: string,
    onClosed?: (window: BrowserWindow) => void
  ): (() => BrowserWindow) => {
    const config = createMainWindowConfig(width, height, minWidth, minHeight, icon)
    const route: RouteConfig = { hash: 'home' }
    const handlers = createDefaultEventHandlers(this.exitManager, 'main', onClosed)

    return createWindow(config, route, handlers)
  }

  /**
   * 创建自定义窗口的工厂方法
   */
  public createCustomWindow = (
    config: WindowConfig,
    route: RouteConfig,
    handlers: WindowEventHandlers
  ): (() => BrowserWindow) => {
    return createWindow(config, route, handlers)
  }
}

/**
 * 获取窗口工厂实例的工厂函数
 */
export const getWindowFactory = (exitManager: AppExitManager): WindowFactory => {
  return WindowFactory.getInstance(exitManager)
}

/**
 * 创建窗口创建器的高阶函数
 */
export const createWindowCreators = (
  exitManager: AppExitManager,
  constants: {
    LOGIN_WIDTH: number
    LOGIN_HEIGHT: number
    MAIN_WIDTH: number
    MAIN_HEIGHT: number
    MIN_WIDTH: number
    MIN_HEIGHT: number
  },
  icon: string,
  windowRefs: {
    setLoginWindow: (window: BrowserWindow | null) => void
    setMainWindow: (window: BrowserWindow | null) => void
  }
): {
  createLoginWindow: () => BrowserWindow
  createMainWindow: () => BrowserWindow
} => {
  const factory = getWindowFactory(exitManager)

  return {
    createLoginWindow: () => {
      const creator = factory.createLoginWindow(
        constants.LOGIN_WIDTH,
        constants.LOGIN_HEIGHT,
        icon,
        () => {
          windowRefs.setLoginWindow(null)
          exitManager.setLoginWindow(null)
        }
      )

      const window = creator()
      windowRefs.setLoginWindow(window)
      exitManager.setLoginWindow(window)
      return window
    },

    createMainWindow: () => {
      const creator = factory.createMainWindow(
        constants.MAIN_WIDTH,
        constants.MAIN_HEIGHT,
        constants.MIN_WIDTH,
        constants.MIN_HEIGHT,
        icon,
        () => {
          windowRefs.setMainWindow(null)
          exitManager.setMainWindow(null)
        }
      )

      const window = creator()
      windowRefs.setMainWindow(window)
      exitManager.setMainWindow(window)
      return window
    }
  }
}
